#include "LecteurPhraseAvecTable.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseAvecTable::LecteurPhraseAvecTable(string nomFich) :
	ls(nomFich), ts() {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::programme() {
// <programme> ::= debut <seqInst> fin <EOF>

	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour() == "si" || ls.getSymCour() == "tantque" || ls.getSymCour() == "repeter" || ls.getSymCour() == "pour" || ls.getSymCour() == "lire" || ls.getSymCour() == "ecrire");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::inst() {
// <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>
	if ( ls.getSymCour() == "si" )
		instSi();
	else if ( ls.getSymCour() == "tantque" )
		instTq();
	else if ( ls.getSymCour() == "repeter" )
		instRepeter();
	else if ( ls.getSymCour() == "pour" )
		instPour();
	else if ( ls.getSymCour() == "lire" )
		instLire();
	else if ( ls.getSymCour() == "ecrire" )
		instEcrire();
	else
		affectation();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::affectation() {
// <affectation> ::= <variable> = <expression>

	testerSymCour("<VARIABLE>");
	ts.chercheAjoute(ls.getSymCour());
	ls.suivant();
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::expression() {
// <expression>	::= <terme> { <opAdd> <terme> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  <opUnaire> <expBool> | ( <expBool> )

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>" || ls.getSymCour() == "<CHAINE>") {
		//if ( ls.getSymCour() == "<VARIABLE>" || ls.getSymCour() == "<ENTIER>" )
			ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	}
	else if (ls.getSymCour()=="(")
	{
		ls.suivant();
		expBool();
		sauterSymCour(")");
	}
	else if(ls.getSymCour() == "non" or ls.getSymCour()=="-")
	{
		ls.suivant();
		expBool();
	}
	else
		erreur("<facteur>");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::terme() {
// <terme> ::= <facteur> { <opMult> <facteur> }
	
	facteur();
	while (ls.getSymCour()=="*" || ls.getSymCour()=="/") {
		opMult();
		facteur();
	 }
	
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opAdd() {
// <opAdd> ::= + | -
	
	if (ls.getSymCour() == "+")
		sauterSymCour("+");
	else if (ls.getSymCour() == "-")
		sauterSymCour("-");
	else
		erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opMult() {
// <opMult> ::= * | /
	
	if (ls.getSymCour() == "*")
		sauterSymCour("*");
	else if (ls.getSymCour() == "/")
		sauterSymCour("/");
	else
		erreur("<opMult>");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instSi() {
// <instSi> ::= si ( <expBool> ) alors <seqInst> { sinonsi ( <expBool> ) alors <seqInst> } [ sinon <seqInst> ] finsi

	sauterSymCour("si");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	sauterSymCour("alors");
	seqInst();
	
	while ( ls.getSymCour() == "sinonsi" ) {
		ls.suivant();
		sauterSymCour("(");
		expBool();
		sauterSymCour(")");
		sauterSymCour("alors");
		seqInst();
	}
	
	if ( ls.getSymCour() == "sinon" ) {
		ls.suivant();
		seqInst();
	}
	
	sauterSymCour("finsi");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instTq() {
// <instTq> ::= tantque ( <expBool> ) faire <seqInst> fintantque
	
	sauterSymCour("tantque");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
	sauterSymCour("faire");
	seqInst();
	sauterSymCour("fintantque");
	
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instRepeter() {
// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> ) 
	
	sauterSymCour("repeter");
	seqInst();
	sauterSymCour("jusqua");
	sauterSymCour("(");
	expBool();
	sauterSymCour(")");
		
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instPour() {
// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> ) 
	
	sauterSymCour("pour");
	sauterSymCour("(");
	affectation();
	sauterSymCour(";");
	expBool();
	sauterSymCour(";");
	affectation();
	sauterSymCour(")");
	sauterSymCour("faire");
	seqInst();
	sauterSymCour("finpour");
	
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opUnaire()
{
	if (ls.getSymCour() == "-")
		sauterSymCour("-");
	else if(ls.getSymCour() == "non")
		sauterSymCour("non"); 
	else
		erreur("<opUnaire>");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opRel()		// <opRel> ::=  == | != | < | <= | > | >=
{
	if (ls.getSymCour() == "==")
		sauterSymCour("==");
	else if(ls.getSymCour() == "<")
		sauterSymCour("<"); 
	else if (ls.getSymCour() == "!=")
		sauterSymCour("!=");
	else if(ls.getSymCour() == "<=")
		sauterSymCour("<="); 
	else if (ls.getSymCour() == ">")
		sauterSymCour(">");
	else if(ls.getSymCour() == ">=")
		sauterSymCour(">="); 
	else
		erreur("<opRel>");
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::relation()	// <relation> ::= <expression> { <opRel> <expression> }
{
	expression();
	while(ls.getSymCour() == "==" or ls.getSymCour() == "!=" or ls.getSymCour() == "<=" or ls.getSymCour() == "<"
	or ls.getSymCour() == ">" or ls.getSymCour() == ">=")
	{	
		opRel();
		expression();
	}
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opBoolOu()		// <opBool> ::= ou 
{
	if(ls.getSymCour() == "ou")
		sauterSymCour("ou");
	else
		erreur("<opBoolOu>");
} 

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::opBoolEt()		// <opBool> ::= et 
{
	if(ls.getSymCour() == "et")
		sauterSymCour("et");
	else
		erreur("<opBoolEt>");
} 

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::expBool()		// <expBool> ::= <expBoolEt> { <opBoolOu> <expBoolEt> }
{
	expBoolEt();
	while(ls.getSymCour() == "ou")
	{
		opBoolOu();
		expBoolEt();
	}
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::expBoolEt()	// <expBoolEt> ::= <relation> {<opBoolEt> <relation> }
{
	relation();
	if(ls.getSymCour() == "et")
	{
		opBoolEt();
		relation();
	}
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instLire() {
// <instLire> ::= lire ( <variable> )
	
	sauterSymCour("lire");
	sauterSymCour("(");
	sauterSymCour("<VARIABLE>");
	sauterSymCour(")");
	
}

////////////////////////////////////////////////////////////////////////////////
void  LecteurPhraseAvecTable::instEcrire() {
// <instEcrire> ::= ecrire ( <expression> | <chaine> )
	
	sauterSymCour("ecrire");
	sauterSymCour("(");
	
	if ( ls.getSymCour() == "<CHAINE>" )
		sauterSymCour("<CHAINE>");
	else
		expression();
	
	sauterSymCour(")");
	
}



////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception
}
